package guiTest;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.IOException;
import java.util.Map;

import javax.sound.sampled.AudioFileFormat;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.SourceDataLine;
import javax.swing.*;

public class MP3_Test_Song implements Runnable 
{
	AudioInputStream din;
	AudioFormat decodedFormat;
	SourceDataLine line;
	MP3_Test_Status currentStatus;
	long streamLengthInBytes;
	
	public MP3_Test_Song(MP3_Test_Status songStatus)
	{
		currentStatus = songStatus;
	}
	
	public void setSong(String filename)
	{/*
		if(filename.equals(currentSongFilename))
		{
			return;
		}
		else 
		{
			stopSong();
			loadNewSong();
			//startSong();
		}
		lock = new Object();
		/*playing = false;
		paused = true;	
		
		try
		{
			long fileLength = file.length() * 8;
			System.out.println("FileSize (bits) = " + fileLength);
			
			int frameSizeInBits = decodedFormat.getFrameSize() * 8;
			System.out.println("FrameSize (bits) = " + frameSizeInBits);
			
			float frameRate = decodedFormat.getFrameRate();
			System.out.println("FrameRate (frames / sec) = " + frameRate);
			
			float bitsPerSecond = frameRate * frameSizeInBits;
			System.out.println("Rate (bits / sec) = " + bitsPerSecond);
			
			float sampleRate = decodedFormat.getSampleRate();
			System.out.println("Sample rate = " + sampleRate);
			
			int sampleSize = decodedFormat.getSampleSizeInBits();
			System.out.println("Sample size = " + sampleSize);
			
			float totalSeconds = fileLength / bitsPerSecond;
			System.out.println("Seconds = " + totalSeconds + "  " + (fileLength / 229376.0));
			
			
			//System.out.println("myFileSize: " + myFileSize);
		
			System.out.println("myAudio.getFrameSize(): " + decodedFormat.getFrameSize());
			System.out.println("myAudio.getFrameRate(): " + decodedFormat.getFrameRate());
			
			double duration = fileLength / (decodedFormat.getFrameSize() * decodedFormat.getFrameRate() * 8);
			System.out.println(duration);
			
			AudioFileFormat baseFileFormat =
			    AudioSystem.getAudioFileFormat(file);
			Map properties = baseFileFormat.properties();
			String key_author = "author";
			String author = (String) properties.get(key_author);
			String key_duration = "duration";
			Long duration2 = (Long) properties.get(key_duration);
			
			System.out.println(duration2);
		}
		catch(Exception e) 
		{
			e.printStackTrace();
		}*/
	}
	
	public void loadSong()
	{
		try
		{
			boolean wasDragging = false;
			if(currentStatus.isAfterDrag())
			{
				wasDragging = true;
				currentStatus.setIsAfterDrag(false);
			}
			
			String currentSongPath = currentStatus.getCurrentSongPath();
			/*File file = new File("C:\\Documents and Settings\\BJ\\My Documents\\" + 
					"My Files\\HTML_Stuff\\mp3_music\\abba\\track01.mp3");*/
			File file = new File(currentSongPath);
			//System.out.println("Loading song: " + currentSongPath);
			//System.out.println("Here, loading song: " + file.getAbsolutePath());
			AudioInputStream in = AudioSystem.getAudioInputStream(file);
			AudioFormat baseFormat = in.getFormat();
			decodedFormat = 
				new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, baseFormat.getSampleRate(),
						16, baseFormat.getChannels(), baseFormat.getChannels() * 2, 
						baseFormat.getSampleRate(), false);
			
			din = AudioSystem.getAudioInputStream(decodedFormat, in);
			DataLine.Info info = new DataLine.Info(SourceDataLine.class, decodedFormat);
			line = (SourceDataLine) AudioSystem.getLine(info);
			
			streamLengthInBytes = (long)file.length();
			//din.getFrameLength() * din.getFormat().getFrameSize();
			//System.out.println("" + din.getFrameLength() + " * " + 
			//		din.getFormat().getFrameSize());
			
			if(wasDragging)
			{
				long g = din.skip((long)(streamLengthInBytes * currentStatus.getPercent()));
				//System.out.println("dragged - " + currentStatus.getPercent() + " - " + g + 
				//		" - " + streamLengthInBytes);
			}

			//din.mark((int)streamLengthInBytes);
		}
		catch(Exception e)
		{
			e.printStackTrace();
		}
	}
	/*
	public void loadNewSong(File file)
	{
		try
		{
			//System.out.println("Here, loading song: " + file.getAbsolutePath());
			AudioInputStream in = AudioSystem.getAudioInputStream(file);
			AudioFormat baseFormat = in.getFormat();
			decodedFormat = 
				new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, baseFormat.getSampleRate(),
						16, baseFormat.getChannels(), baseFormat.getChannels() * 2, 
						baseFormat.getSampleRate(), false);
			
			din = AudioSystem.getAudioInputStream(decodedFormat, in);
			DataLine.Info info = new DataLine.Info(SourceDataLine.class, decodedFormat);
			line = (SourceDataLine) AudioSystem.getLine(info);
			
		}
		catch(Exception e)
		{
			e.printStackTrace();
		}
	}
	*/
	
	/*
	public AudioInputStream getAudioStream()
	{
		return din;
	}*/
	
	public void playMusic()
	{
		try
		{
			while(true)
			{
				//System.out.println("Beginning of loop");
				
				if(currentStatus.isNewSong())
				{
					loadSong();
					currentStatus.setNotNewSong();
				}
				/*
				while(!currentStatus.isSongReady())
				{
					System.out.println("Song not ready, calling wait... ");
					
					synchronized(currentStatus)
					{
						currentStatus.wait();
						loadNewSong(new File("c:\\temp\\" + currentStatus.getSongName()));
					}
				}			
			*/
				boolean songEndedNormally = true;
				
				if(line != null)
				{
					boolean continueLoop = true;
					line.open(decodedFormat);
					byte[] data = new byte[4096];

					// Start
					line.start();
					int nBytesRead = din.read(data, 0, data.length);
					
					while(nBytesRead != -1 && continueLoop) 
					{
						while(currentStatus.isPaused()) 
						{
							if(line.isRunning()) 
							{
								line.stop();
							}
							
							//System.out.println("Calling wait... ");
							
							synchronized(currentStatus)
							{
								currentStatus.wait();
							}
							
							if(currentStatus.isAfterDrag())
							{
								line.flush();
								//line.stop();
								//line.close();
								//din.close();
								currentStatus.setNewSong();
							}
							
							
						}
											
						if(currentStatus.isNewSong())
						{
							line.stop();
							continueLoop = false;
							songEndedNormally = false;
						}
						else
						{
							if(!line.isRunning())
							{
								line.start();								
							}	
						}
						
						if(continueLoop)
						{
							line.write(data, 0, nBytesRead);
							nBytesRead = din.read(data, 0, data.length);
														
							if(nBytesRead < 0)
							{
								songEndedNormally = true;
							}
						}
					}
					
									
					// Stop
					line.drain();
					line.stop();
					line.close();
					//din.reset();
					din.close();
					
					//System.out.println("Song ended.");
					//currentStatus.setSongNotReady();
					
					if(!songEndedNormally)
					{
						// In this case, the user requested a new song and
						// we assume that the new song object is set in the currentStatus object
						loadSong();
						currentStatus.setNotNewSong();
					}
					else
					{
						// The song ended normally
						int currentPlayMode = currentStatus.getMode();
						
						if(currentPlayMode == MP3_Test_Status.MODE_LOOP)
						{
							currentStatus.requestNextSong();
							loadSong();
						}
						else if(currentPlayMode == MP3_Test_Status.MODE_REPEAT)
						{
							loadSong();
						}
						else if(currentPlayMode == MP3_Test_Status.MODE_REVERSE_LOOP)
						{
							currentStatus.requestPreviousSong();
							loadSong();
						}
						else if(currentPlayMode == MP3_Test_Status.MODE_RANDOM)
						{
							currentStatus.requestRandomSong();
							loadSong();
						}
						
						currentStatus.setNotNewSong();
					}
					
				}
				else
				{
					System.out.println("Line is null!!");
				}
								
				//System.out.println("This is the out data");
				//System.out.println("Not Paused");
			}
		}
		catch(Exception e)
		{
			
		}
		finally
		{
			if(din != null) 
			{
				try 
				{ 
					din.close(); 
				} 
				catch(IOException e) 
				{ 
					e.printStackTrace();
				}
			}
		}
		
	}
	
	public void run()
	{
		playMusic();		
	}

}
